package edu.cmu.cs.stage3.alice.authoringtool.util;

public class DefaultUndoRedoStack extends java.util.LinkedList implements UndoRedoStack {

 private int currentIndex = -1;

 // Came from: edu.cmu.cs.stage3.alice.authoringtool.MainUndoRedoStack.startCompound()
 synchronized public void push (UndoableRedoable ur) {
  if (currentIndex < (size() - 1)) { //is the current index the last item added
   removeRange( currentIndex + 1, size() );
   }
  // System.out.println("DefaultUndoRedoStack.java: push(UndoableRedoable): currentIndex="+currentIndex+": "+edu.cmu.cs.stage3.util.StrUtilities.getComponentName(ur));
  // try{String str=""; System.out.println(str.charAt(3));}catch(Exception e){e.printStackTrace();}
  addLast( ur ); // edu.cmu.cs.stage3.alice.authoringtool.util.CompoundUndoableRedoable ur
  currentIndex = size() - 1;
  }

 synchronized public UndoableRedoable pop () {
  if (currentIndex == (size() - 1)) {
   currentIndex--;
   }
  return (UndoableRedoable)removeLast();
  }

 synchronized public UndoableRedoable undo () {
  if (currentIndex > -1) {
   UndoableRedoable ur = (UndoableRedoable)get( currentIndex );
   // System.out.println("DefaultUndoRedoStack.java: undo(): currentIndex="+currentIndex+": "+edu.cmu.cs.stage3.util.StrUtilities.getComponentName(ur.getContext()));
   ur.undo(); // edu.cmu.cs.stage3.alice.authoringtool.util.CompoundUndoableRedoable.undo()
   currentIndex--;
   return ur;
  } else {
   return null;
   }
  }

 synchronized public UndoableRedoable redo () {
  if (currentIndex < (size() - 1)) {
   currentIndex++;
   UndoableRedoable ur = (UndoableRedoable)get( currentIndex );
   ur.redo();
   return ur;
  } else {
   return null;
   }
  }

 synchronized public UndoableRedoable removeUndoable (int index) {
  if ((index < 0) || (index > (size() - 1))) {
   return null;
   }
  if (index > currentIndex) {
   return (UndoableRedoable)remove( index );
   }

  UndoableRedoable removedItem = null;
  java.util.ListIterator iter = listIterator();
  while (iter.nextIndex() <= currentIndex) {
   iter.next();
   }
  while (iter.previousIndex() >= index) {
   UndoableRedoable ur = (UndoableRedoable)iter.previous();
   ur.undo();
   removedItem = ur;
   }
  iter.remove();
  currentIndex--;
  while (iter.nextIndex() <= currentIndex) {
   UndoableRedoable ur = (UndoableRedoable)iter.next();
   ur.redo();
   }

  return removedItem;
  }

 synchronized public int getCurrentUndoableRedoableIndex () {
  return currentIndex;
  }

 synchronized public UndoableRedoable getCurrentUndoableRedoable () {
  return (UndoableRedoable)get( currentIndex );
  }

 //Rem @Override
 synchronized public void clear () {
  super.clear();
  currentIndex = -1;
  }

 }
